package com.njtoyo.taxi.admin.service.business.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njtoyo.taxi.admin.library.Const;
import com.njtoyo.taxi.admin.library.common.Enum;
import com.njtoyo.taxi.admin.library.common.GeoPoint;
import com.njtoyo.taxi.admin.library.common.OperationRecordHelper;
import com.njtoyo.taxi.admin.library.taxi_service.SimpleCallTaxiService;
import com.njtoyo.taxi.admin.logic.business.simple_call.SimpleCallBackLogLogic;
import com.njtoyo.taxi.admin.logic.business.simple_call.SimpleCallRideLogic;
import com.njtoyo.taxi.admin.mapper.master.entity.*;
import com.njtoyo.taxi.admin.mapper.master.enums.SimpleCallRideCategory;
import com.njtoyo.taxi.admin.mapper.master.enums.SimpleCallRideState;
import com.njtoyo.taxi.admin.mapper.master.enums.SimpleCallState;
import com.njtoyo.taxi.admin.mapper.master.mapper.*;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.AdminUserMapper;
import com.njtoyo.taxi.admin.rest.presenter.business.simple_call.ListPresenter;
import com.njtoyo.taxi.admin.rest.presenter.platfrom.AdminUserIdentityPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.business.simple_call.SimpleCallQueryWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.business.simple_call.backlog.SendPhoneWrapper;
import com.njtoyo.taxi.admin.service.business.BusinessSimpleCallService;
import com.njtoyo.taxi.admin.service.business.SimpleCallBacklogService;
import com.njtoyo.taxi.admin.utils.AuthUtil;
import com.njtoyo.taxi.entity.backend.AdminUser;
import com.taxi.entity.common.RestResult;
import com.taxi.entity.common.ResultEnum;
import org.nutz.lang.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
@DS(Const.PRIMARY_DS)
public class BusinessSimpleCallServiceImpl implements BusinessSimpleCallService {

    @Autowired
    private SimpleCallMapper simpleCallMapper;

    @Autowired
    private SimpleCallRideMapper simpleCallRideMapper;

    @Autowired
    private SimpleCallRideLogic simpleCallRideLogic;

    @Autowired
    private SimpleCallCustomerMapper simpleCallCustomerMapper;

    @Autowired
    private DriverMapper driverMapper;

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private TaxiMapper taxiMapper;

    @Autowired
    private GeoCantonMapper geoCantonMapper;

    @Autowired
    private GeoAreaMapper geoAreaMapper;

    @Autowired
    private SimpleCallBackLogLogic simpleCallBackLogLogic;

    @Autowired
    private SimpleCallMediaMapper simpleCallMediaMapper;

    @Autowired
    private SimpleCallTaxiService simpleCallTaxiService;
    @Autowired
    private OperationRecordHelper operationRecordHelper;
    @Autowired
    private AdminUserMapper adminUserMapper;
    @Autowired
    private SimpleCallBacklogService simpleCallBacklogService;
    @Autowired
    private SimpleCallRideCancellationMapper simpleCallRideCancellationMapper;

    @Override
    public RestResult<IPage<ListPresenter>> getList(AdminUser adminUser,SimpleCallQueryWrapper queryWrapper) {
        LambdaQueryChainWrapper<SimpleCall> query = new LambdaQueryChainWrapper<>(simpleCallMapper);
        // 电召
        if (ObjectUtil.isNull(queryWrapper.getCategory())) {
            query.in(SimpleCall::getCategory, Arrays.asList(SimpleCallRideCategory.phone, SimpleCallRideCategory.phone_appointment));
        } else {
            query.eq(SimpleCall::getCategory, queryWrapper.getCategory());
        }
        if (StrUtil.isNotBlank(queryWrapper.getStartDate()) && StrUtil.isNotBlank(queryWrapper.getEndDate())) {
            query.between(SimpleCall::getCreatedAt, queryWrapper.getStartDate(), queryWrapper.getEndDate());
        }

        AdminUserIdentityPresenter identity = (AdminUserIdentityPresenter) adminUser.getIdentity();
        switch (adminUser.getAccountType()) {
            case canton:
                // 1. 行政区
                query.in(SimpleCall::getCantonId, identity.getCantonIds());
                break;
        }


        // 2. 叫车状态
        query.eq(ObjectUtil.isNotEmpty(queryWrapper.getState()), SimpleCall::getState, queryWrapper.getState());

        // 3. 乘客搜索
        String customerSearch = queryWrapper.getCustomerSearch();

        if (ObjectUtil.isNotEmpty(customerSearch)) {
            if (this.isPhoneNum(customerSearch)) {
                query.inSql(SimpleCall::getCustomerId, String.format("SELECT id FROM simple_call_customer WHERE mobile_number = '%s'", customerSearch));
            } else {
                query.inSql(SimpleCall::getCustomerId, String.format("SELECT id FROM simple_call_customer WHERE name LIKE '%%%s%%'", customerSearch));
            }
        }

        if (StrUtil.isNotBlank(queryWrapper.getAdminName())) {
            com.njtoyo.taxi.admin.mapper.secondary.entity.AdminUser adminUsers = adminUserMapper.selectOne(Wrappers.<com.njtoyo.taxi.admin.mapper.secondary.entity.AdminUser>lambdaQuery()
                    .eq(com.njtoyo.taxi.admin.mapper.secondary.entity.AdminUser::getName, queryWrapper.getAdminName()));
            if (ObjectUtil.isNull(adminUsers)) {
                return RestResult.success(new Page<>());
            } else {
                query.eq(SimpleCall::getAdminId, adminUsers.getId());
            }
        }

        Page<SimpleCall> page = new Page<>(queryWrapper.getCurrent(), queryWrapper.getSize());

        IPage<SimpleCall> list = query.orderByDesc(SimpleCall::getId).page(page);

        if (ObjectUtil.isEmpty(list.getRecords())) {
            return RestResult.success(new Page<>());
        }

        Set<Long> simpleCallIds = new HashSet<>();
        Set<Long> customerIds = new HashSet<>();
        Set<Long> cantonIds = new HashSet<>();
        Set<Long> areaIds = new HashSet<>();
        Set<Long> mediaIds = new HashSet<>();
        Set<Integer> adminIds = new HashSet<>();

        list.getRecords().forEach(call -> {
            simpleCallIds.add(call.getId());
            customerIds.add(call.getCustomerId());
            cantonIds.add(call.getCantonId());
            areaIds.add(call.getAreaId());
            mediaIds.add(call.getMediaId());
            adminIds.add(call.getAdminId());
        });
        // 1. 查 simple_call_ride
        List<SimpleCallRide> simpleCallRideList = simpleCallRideLogic.selectRealOriginBySimpleCallIds(simpleCallIds);

        Map<Long, SimpleCallRide> simpleCallRideMap = new HashMap<>();
        Map<Long, Driver> driverMap = new HashMap<>();
        Map<Long, String> companyMap = new HashMap<>();
        Map<Long, String> taxiMap = new HashMap<>();

        if (ObjectUtil.isNotEmpty(simpleCallRideList)) {
            simpleCallRideMap = simpleCallRideList.stream().collect(Collectors.toMap(SimpleCallRide::getRefId, i -> i));

            // 查司机、公司、车辆
            Set<Long> driverIds = new HashSet<>();
            Set<Long> companyIds = new HashSet<>();
            Set<Long> taxiIds = new HashSet<>();
            simpleCallRideList.forEach(ride -> {
                driverIds.add(ride.getDriverId());
                companyIds.add(ride.getCompanyId());
                taxiIds.add(ride.getTaxiId());
            });

            if (ObjectUtil.isNotEmpty(driverIds)) {
                List<Driver> driverList = driverMapper.selectBatchIds(driverIds);
                driverMap = driverList.stream().collect(Collectors.toMap(Driver::getId, i -> i));
            }
            if (ObjectUtil.isNotEmpty(companyIds)) {
                List<Company> companyList = companyMapper.selectBatchIds(companyIds);
                companyMap = companyList.stream().collect(Collectors.toMap(Company::getId, Company::getName));
            }
            if (ObjectUtil.isNotEmpty(taxiIds)) {
                List<Taxi> taxiList = taxiMapper.selectBatchIds(taxiIds);
                taxiMap = taxiList.stream().collect(Collectors.toMap(Taxi::getId, Taxi::getPlateNumber));
            }
        }

        // 2. 查乘客
        Map<Long, SimpleCallCustomer> customerMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(customerIds)) {
            List<SimpleCallCustomer> customerList = simpleCallCustomerMapper.selectBatchIds(customerIds);
            if (ObjectUtil.isNotEmpty(customerList)) {
                customerMap = customerList.stream().collect(Collectors.toMap(SimpleCallCustomer::getId, i -> i));
            }
        }

        // 3. 查 canton
        Map<Long, String> cantonMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(cantonIds)) {
            List<GeoCanton> cantonList = geoCantonMapper.selectBatchIds(cantonIds);
            if (ObjectUtil.isNotEmpty(cantonList)) {
                cantonMap = cantonList.stream().collect(Collectors.toMap(GeoCanton::getId, GeoCanton::getName));
            }
        }

        // 4. 查 area
        Map<Long, String> areaMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(areaIds)) {
            List<GeoArea> areaList = geoAreaMapper.selectBatchIds(areaIds);
            if (ObjectUtil.isNotEmpty(areaList)) {
                areaMap = areaList.stream().collect(Collectors.toMap(GeoArea::getId, GeoArea::getName));
            }
        }

        // 4. 查 simple_call_backlog
        List<SimpleCallBacklog> simpleCallBacklogList = simpleCallBackLogLogic.selectBySimpleCallIds(simpleCallIds);
        // simpleCallId => callAudioUrl
        Map<Long, String> simpleCallBacklogMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(simpleCallBacklogList)) {
            simpleCallBacklogMap = simpleCallBacklogList.stream().filter(e -> Objects.nonNull(e.getAudioUrl())).collect(Collectors.toMap(SimpleCallBacklog::getCallId, SimpleCallBacklog::getAudioUrl, (oldVal, newVal) -> newVal));
        }

        // 5. 查 simple_call_media
        Map<Long, Date> simpleCallMediaMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(mediaIds)) {
            List<SimpleCallMedia> simpleCallMediaList = simpleCallMediaMapper.selectBatchIds(mediaIds);
            // mediaId => callBacklogCreatedAt
            if (ObjectUtil.isNotEmpty(simpleCallMediaList)) {
                simpleCallMediaMap = simpleCallMediaList.stream().collect(Collectors.toMap(SimpleCallMedia::getId, SimpleCallMedia::getCreatedAt));
            }
        }

        Map<Integer, String> simpleCallAdminMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(adminIds)) {
            List<com.njtoyo.taxi.admin.mapper.secondary.entity.AdminUser> adminUsers = adminUserMapper.selectBatchIds(adminIds);
            if (CollUtil.isNotEmpty(adminUsers)) {
                simpleCallAdminMap = adminUsers.stream().collect(Collectors.toMap(com.njtoyo.taxi.admin.mapper.secondary.entity.AdminUser::getId, com.njtoyo.taxi.admin.mapper.secondary.entity.AdminUser::getName));
            }
        }

        Map<Long, SimpleCallRide> finalSimpleCallRideMap = simpleCallRideMap;
        Map<Long, SimpleCallCustomer> finalCustomerMap = customerMap;
        Map<Long, Driver> finalDriverMap = driverMap;
        Map<Long, String> finalCompanyMap = companyMap;
        Map<Long, String> finalTaxiMap = taxiMap;
        Map<Long, String> finalCantonMap = cantonMap;
        Map<Long, String> finalAreaMap = areaMap;
        Map<Long, String> finalSimpleCallBacklogMap = simpleCallBacklogMap;
        Map<Long, Date> finalSimpleCallMediaMap = simpleCallMediaMap;
        Map<Integer, String> finalSimpleCallAdminMap = simpleCallAdminMap;

        IPage<ListPresenter> res = list.convert(i -> {
            ListPresenter response = new ListPresenter();
            response.setId(i.getId());
            response.setCreatedAt(i.getCreatedAt());
            response.setState(i.getState());
            response.setCategory(i.getCategory());
            response.setOriginName(i.getOriginName());
            response.setOriginPlaceName(i.getOriginPlaceName());
            response.setDestinationName(i.getDestinationName());
            response.setDestinationPlaceName(i.getDestinationPlaceName());
            response.setAdminName(finalSimpleCallAdminMap.get(i.getAdminId()));
            response.setCallMode(i.getCallMode());


            // 设置 simple_call_ride
            // 判断是否有行程
            if (ObjectUtil.isNotEmpty(finalSimpleCallRideMap)) {
                SimpleCallRide itemRide = finalSimpleCallRideMap.get(i.getId());
                // 判断行程是否存在
                if (ObjectUtil.isNotEmpty(itemRide)) {
                    response.setRealOriginName(itemRide.getRealOriginName());
                    response.setRealOriginPlaceName(itemRide.getRealOriginPlaceName());


                    Driver itemDriver = finalDriverMap.get(itemRide.getDriverId());
                    if (ObjectUtil.isNotEmpty(itemDriver)) {
                        response.setDriverId(itemDriver.getId());
                        response.setDriverName(itemDriver.getName());
                        response.setDriverMobileNumber(itemDriver.getMobileNumber());
                    }

                    String itemCompanyName = finalCompanyMap.get(itemRide.getCompanyId());
                    if (ObjectUtil.isNotEmpty(itemCompanyName)) {
                        response.setCompanyId(itemRide.getCompanyId());
                        response.setCompanyName(itemCompanyName);
                    }

                    String itemTaxiPlateNumber = finalTaxiMap.get(itemRide.getTaxiId());
                    if (ObjectUtil.isNotEmpty(itemTaxiPlateNumber)) {
                        response.setTaxiId(itemRide.getTaxiId());
                        response.setTaxiPlateNumber(itemTaxiPlateNumber);
                    }
                }
            }

            // 设置 simple_call_customer
            SimpleCallCustomer itemCustomer = finalCustomerMap.get(i.getCustomerId());
            if (ObjectUtil.isNotEmpty(itemCustomer)) {
                response.setCustomerId(itemCustomer.getId());
                response.setCustomerName(itemCustomer.getName());
                response.setCustomerMobileNumber(itemCustomer.getMobileNumber());
            }

            // 设置 geo_canton
            String itemCantonName = finalCantonMap.get(i.getCantonId());
            if (ObjectUtil.isNotEmpty(itemCantonName)) {
                response.setCantonId(i.getCantonId());
                response.setCantonName(itemCantonName);
            }

            // 设置 areaMap
            String itemAreaName = finalAreaMap.get(i.getAreaId());
            if (ObjectUtil.isNotEmpty(itemAreaName)) {
                response.setAreaId(i.getAreaId());
                response.setAreaName(itemAreaName);
            }

            // 设置 simpleCallBacklogMap
            response.setCallAudioUrl(finalSimpleCallBacklogMap.getOrDefault(i.getId(), null));

            // 设置 simpleCallBacklogMap
            response.setCallBacklogCreatedAt(finalSimpleCallMediaMap.get(i.getMediaId()));

            return response;
        });

        return RestResult.success(res);
    }

    @Override
    public RestResult<SimpleCall> detail(Long id) {
        return RestResult.success(simpleCallMapper.selectById(id));
    }

    @Override
    public RestResult<SimpleCall> cancel(Long id) {
        SimpleCall simpleCall = simpleCallMapper.selectById(id);
        if (Objects.isNull(simpleCall)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }
        // 判断行程状态
        if (simpleCall.getState().equals(SimpleCallState.cancelled) || simpleCall.getState().equals(SimpleCallState.covered) || simpleCall.getState().equals(SimpleCallState.cancel_admin)) {
            return RestResult.failed("行程已取消");
        }
        SimpleCallRide simpleCallRide = simpleCallRideMapper.selectOne(Wrappers.<SimpleCallRide>lambdaQuery().eq(SimpleCallRide::getRefId, id));
        if (ObjectUtil.isNotNull(simpleCallRide) && (simpleCallRide.getState() == SimpleCallRideState.start || simpleCallRide.getState() == SimpleCallRideState.end)) {
            return RestResult.failed(StrUtil.format("行程{}无法取消", simpleCall.getState().name()));
        }
        if (ObjectUtil.isNotNull(simpleCallRide) && simpleCallRide.getState() == SimpleCallRideState.pickUp) {
            return RestResult.failed("司机已接单,请到行程列表里取消！");
        }
        new LambdaUpdateChainWrapper<>(simpleCallMapper).eq(SimpleCall::getId, simpleCall.getId()).set(SimpleCall::getState, 4).update();
        simpleCallTaxiService.sendCancelCallMqtt(id, Boolean.TRUE);
        return RestResult.success();
    }

    @Override
    public RestResult getHisoryOriginTop3ByPhone(String phone) {
        List<Dict> origins = simpleCallMapper.getHisoryOriginTop3ByPhone(phone);
        return RestResult.success(origins);
    }

    @Override
    public RestResult getLoginUserCall() {
        AdminUser userInfo = AuthUtil.getUserInfo();
        List<SimpleCall> list = simpleCallMapper.selectList(Wrappers.<SimpleCall>lambdaQuery().eq(SimpleCall::getAdminId, userInfo.getId()).orderByDesc(SimpleCall::getCreatedAt).last(" limit 2"));

        List<Dict> dicts = new ArrayList<>();
        list.forEach(i -> {
            SimpleCallCustomer user = simpleCallCustomerMapper.selectById(i.getCustomerId());
            Dict dict = new Dict();
            dict.put("id", i.getId());
            dict.put("callType", i.getCategory());
            dict.put("createDate", DateUtil.formatDateTime(i.getCreatedAt()));
            dict.put("customerPhone", user.getMobileNumber());
            dict.put("originName", i.getOriginName());
            if (i.getState() != SimpleCallState.pick) {
                dict.put("state", i.getState());
            } else {
                SimpleCallRide simpleCallRide = simpleCallRideMapper.selectOne(Wrappers.<SimpleCallRide>lambdaQuery().eq(SimpleCallRide::getRefId, i.getId()));
                if (ObjectUtil.isNotNull(simpleCallRide)) {
                    if (simpleCallRide.getIsCancel()) {
                        SimpleCallRideCancellation simpleCallRideCancellation = simpleCallRideCancellationMapper.selectOne(Wrappers.<SimpleCallRideCancellation>lambdaQuery()
                                .eq(SimpleCallRideCancellation::getRideId, simpleCallRide.getId()));
                        dict.put("state", simpleCallRideCancellation.getTriggerBy().name());
                    } else {
                        dict.put("state", simpleCallRide.getState());
                    }

                }
            }
            SimpleCallRide ride = simpleCallRideMapper.selectOne(Wrappers.<SimpleCallRide>lambdaQuery().eq(SimpleCallRide::getRefId, i.getId()));
            if (ObjectUtil.isNotNull(ride)) {
                Driver driver = driverMapper.selectById(ride.getDriverId());
                Taxi taxi = taxiMapper.selectById(ride.getTaxiId());
                dict.put("mobileNumber", driver.getMobileNumber());
                dict.put("plateNumber", taxi.getPlateNumber());
            }
            dicts.add(dict);
        });
        return RestResult.success(dicts);
    }


    private Boolean isPhoneNum(String content) {
        return ReUtil.isMatch("^1[0-9]\\d{9}$", content);
    }


    @Override
    public RestResult reCallById(Long id) {
        Dict recall = simpleCallMapper.getReCallInfo(id);
        if (ObjectUtil.isNull(recall)) {
            return RestResult.failed("呼叫失败,原单已不存在!");
        }
        return RestResult.success(recall);
    }

    @Override
    public RestResult getReCallInfo(Long id) {
        SimpleCall simpleCall = simpleCallMapper.selectById(id);
        Dict dict = new Dict();
        if (ObjectUtil.isNotNull(simpleCall)) {
            SimpleCallCustomer simpleCallCustomer = simpleCallCustomerMapper.selectById(simpleCall.getCustomerId());
            dict.put("mobileNumber", simpleCallCustomer.getMobileNumber());
            dict.put("call", simpleCall);
        }
        return RestResult.success(dict);
    }
}
